﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CoreUC
{
    public partial class ImageView : UserControl
    {
        /// <summary>
        /// Image view tool control
        /// </summary>
        /// <remarks>trungpv@vnext.vn</remarks>
        #region Attributs and Getter/Setter
        private FVIL.Forms.CFviImageView m_image;
        private bool m_isActiveAscope;
        public EventHandler eventSaveImage;
        public EventHandler eventCloseSaveDialog;
        public EventHandler eventOpenImage;

        public bool IsActiveAscope
        {
            get { return m_isActiveAscope; }
            set { m_isActiveAscope = value; }
        }
        public FVIL.Forms.CFviImageView Image
        {
            get { return m_image; }
            set { m_image = value; }
        }
        #endregion

        public ImageView()
        {
            InitializeComponent();
            // Set tooltip for controls
            ToolTip toolTip = new ToolTip();
            toolTip.ShowAlways = true;
            toolTip.SetToolTip(this.btnFit, "Fit");
            toolTip.SetToolTip(this.btnAscope, "Ascope");
            toolTip.SetToolTip(this.btnOpen, "Open");
            toolTip.SetToolTip(this.btnSave, "Save");
        }

        #region Logic functions
        /// <summary>
        /// Initialize parameters for control
        /// </summary>
        /// <param name="image"></param>
        /// <param name="isActiveAscope"></param>
        public void setImageView(FVIL.Forms.CFviImageView image, bool isActiveAscope)
        {
            m_image = image;
            m_isActiveAscope = isActiveAscope;
            btnAscope.Enabled = isActiveAscope; // Enable/Disable ascope button
            btnOpen.Enabled = isActiveAscope; // Enable/Disable open button
            btnAscope.Refresh();
            createMouseScrollEvent();
            m_image.EnableMouseGrip = true; // Allow to use scroll mouse
            updateZoomScale(m_image.Display.Magnification);
            m_image.Refresh();
        }

        /// <summary>
        /// Mouse scroll event
        /// </summary>
        private void createMouseScrollEvent()
        {
            // Remove mouse wheel event if it exists
            if (m_image != null)
            {
                m_image.MouseWheel -=
                    new System.Windows.Forms.MouseEventHandler(this.image_MouseWheel);
                this.m_image.MouseHover -=
                    new System.EventHandler(this.image_MouseHover);
            }
            m_image.MouseWheel +=
                new System.Windows.Forms.MouseEventHandler(this.image_MouseWheel);
            this.m_image.MouseHover +=
                new System.EventHandler(this.image_MouseHover);
        }

        /// <summary>
        /// Update zoom scale text
        /// </summary>
        /// <param name="value"></param>
        public void updateZoomScale(double value)
        {
            double scalValue = 100 * value;
            slZoom.Text = ((int)scalValue).ToString() + "%";
            if (scalValue < 100)
            {
                slZoom.Value = (int)(4 * scalValue - 40);
            }
            else
            {
                slZoom.Value = (int)(0.9 * scalValue + 270);
            }
        }

        /// <summary>
        /// Zoom in control
        /// </summary>
        public void zoomIn()
        {
            double value = 0;
            value = m_image.Display.Magnification;
            value = Math.Floor(value * 10 + 1) / 10;
            m_image.Display.Magnification = value;
            m_image.Refresh();
            updateZoomScale(value);
        }

        /// <summary>
        /// Zoom out control
        /// </summary>
        public void zoomOut()
        {
            double value = 0;
            value = m_image.Display.Magnification;
            // Min zoom scale = 10%
            if (value > 0.1)
                value = Math.Ceiling(value * 10 - 1) / 10;
            m_image.Display.Magnification = value;
            m_image.Refresh();
            updateZoomScale(value);
        }

        /// <summary>
        /// Save image function
        /// </summary>
        /// <param name="image"></param>
        public void saveImage(FVIL.Data.CFviImage image)
        {
            if (image != null)
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter =
                    "Windows Bitmap|*.bmp|Portable Network Graphics|*.png|JPEG File Format|*.jpg|"
                    + "Tagged Image File Format|*.Tiff|All|*.*";
                saveFileDialog.Title = "イメージを保存します。";
                saveFileDialog.ShowDialog();
                if (saveFileDialog.FileName != "")
                {
                    image.Save(saveFileDialog.FileName);
                    System.Windows.Forms.MessageBox.Show("保存しました。", "メッセージ", MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show("保存する画像がありません。再度確認してください。", "警報",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        /// <summary>
        /// Open an image
        /// </summary>
        public void openImage()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter =
                "Windows Bitmap|*.bmp|Portable Network Graphics|*.png|JPEG File Format|*.jpg|"
                + "Tagged Image File Format|*.Tiff|All|*.*";
            openFileDialog.Title = "Load Image";
            FVIL.Data.CFviImage src = new FVIL.Data.CFviImage();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                if (!String.IsNullOrEmpty(openFileDialog.FileName))
                {
                    try
                    {
                        src.Load(openFileDialog.FileName);
                    }
                    catch (Exception)
                    {
                        System.Windows.Forms.MessageBox.Show("Invalid image");
                        return;
                    }
                    m_image.Image = src;
                    m_image.Refresh();
                }
            }
        }
        #endregion

        #region Click events
        private void btnFit_Click(object sender, EventArgs e)
        {
            if (m_image == null) return;
            m_image.FitImageSize();
            updateZoomScale(m_image.Display.Magnification);
            m_image.FitImageSize(); // fit twice 
            m_image.Refresh();
        }

        private void btnAscope_Click(object sender, EventArgs e)
        {
            if (m_image == null || m_image.Image == null || !m_isActiveAscope)
            {
                MessageBox.Show("画像がありません。再度確認してください。", "警報", MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
                return;
            }
            m_image.Display.OverlayAscope.Enable = !m_image.Display.OverlayAscope.Enable;
            m_image.Display.OverlayAscope.Active = !m_image.Display.OverlayAscope.Active;
            m_image.Refresh();
            if (m_image.Display.OverlayAscope.Enable)
            {
                btnAscope.FlatAppearance.BorderColor = Color.FromArgb(51, 153, 255);
                btnAscope.BackColor = Color.FromArgb(194, 224, 255);
                btnAscope.MouseLeave -= new EventHandler(tsBtnAscope_MouseLeave);
                btnAscope.MouseMove -= new MouseEventHandler(tsBtnAscope_MouseMove);
                btnAscope.Refresh();
            }
            else
            {
                btnAscope.FlatAppearance.BorderColor = Color.FromArgb(187, 206, 230);
                btnAscope.BackColor = Color.FromArgb(187, 206, 230);
                btnAscope.MouseLeave += new EventHandler(tsBtnAscope_MouseLeave);
                btnAscope.MouseMove += new MouseEventHandler(tsBtnAscope_MouseMove);
                btnAscope.Refresh();
            }
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            openImage();
            OnOpenClick();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (m_image != null)
            {
                OnSaveClick();
                saveImage(m_image.Image);
                OnCloseSaveDialog();
            }
        }

        private void slZoom_DecreaseButtonClick(object sender, EventArgs e)
        {
            if (slZoom.Value > 360)
            {
                slZoom.Value = ((int)Math.Ceiling((double)slZoom.Value / 9) - 1) * 9;
            }
            else if (slZoom.Value > 0)
            {
                slZoom.Value = ((int)Math.Ceiling((double)slZoom.Value / 40) - 1) * 40;
            }
        }

        private void slZoom_IncreaseButtonClick(object sender, EventArgs e)
        {
            if (slZoom.Value < 360)
            {
                slZoom.Value = ((int)(slZoom.Value / 40) + 1) * 40;
            }
            else if (slZoom.Value <= 720)
            {
                slZoom.Value = ((int)(slZoom.Value / 9) + 1) * 9;
            }
        }

        private void slZoom_ValueChanged(object sender, EventArgs e)
        {
            if (slZoom.Value < 360)
            {
                slZoom.Text = ((int)(slZoom.Value * 0.25 + 10)).ToString() + "%";
            }
            else
            {
                slZoom.Text = ((int)(slZoom.Value * 10 / 9 - 300)).ToString() + "%";
            }
            if (m_image == null) return;
            m_image.Display.Magnification = (double)Convert.ToInt32(slZoom.Text.Remove
                (slZoom.Text.Length - 1)) / 100;
            m_image.Refresh();
        }

        public virtual void OnSaveClick()
        {
            EventHandler handler = eventSaveImage;
            if (handler != null)
            {
                handler(null, EventArgs.Empty);
            }
        }

        public virtual void OnCloseSaveDialog()
        {
            EventHandler handler = eventCloseSaveDialog;
            if (handler != null)
            {
                handler(null, EventArgs.Empty);
            }
        }

        public virtual void OnOpenClick()
        {
            EventHandler handler = eventOpenImage;
            if (handler != null)
            {
                handler(null, EventArgs.Empty);
            }
        }
        #endregion

        #region Mouse events
        private void image_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
                this.zoomIn();
            if (e.Delta < 0)
                this.zoomOut();
        }

        private void image_MouseHover(object sender, EventArgs e)
        {
            m_image.Focus();
        }
        #endregion

        #region Button interface design
        private void btnSave_MouseMove(object sender, MouseEventArgs e)
        {
            btnSave.FlatAppearance.BorderColor = Color.FromArgb(51, 153, 255);
        }

        private void btnSave_MouseLeave(object sender, EventArgs e)
        {
            btnSave.FlatAppearance.BorderColor = System.Drawing.SystemColors.Control;
        }

        private void tsBtnAscope_MouseMove(object sender, MouseEventArgs e)
        {
            btnAscope.FlatAppearance.BorderColor = Color.FromArgb(51, 153, 255);
        }

        private void tsBtnAscope_MouseLeave(object sender, EventArgs e)
        {
            btnAscope.FlatAppearance.BorderColor = System.Drawing.SystemColors.Control;
        }

        private void tsBtnFit_MouseMove(object sender, MouseEventArgs e)
        {
            btnFit.FlatAppearance.BorderColor = Color.FromArgb(51, 153, 255);
        }

        private void tsBtnFit_MouseLeave(object sender, EventArgs e)
        {
            btnFit.FlatAppearance.BorderColor = System.Drawing.SystemColors.Control;
        }


        private void btnOpen_MouseMove(object sender, MouseEventArgs e)
        {
            btnOpen.FlatAppearance.BorderColor = Color.FromArgb(51, 153, 255);
        }

        private void btnOpen_MouseLeave(object sender, EventArgs e)
        {
            btnOpen.FlatAppearance.BorderColor = System.Drawing.SystemColors.Control;
        }
        #endregion
    }
}
